use std::{
    sync::{Arc, Mutex},
    thread,
    time::Duration,
};

use flutter_rust_bridge::frb;
use rusb::{Device, DeviceHandle, GlobalContext, Speed, Version};

use crate::frb_generated::{StreamSink, FLUTTER_RUST_BRIDGE_HANDLER};

#[frb(dart_metadata=("freezed", "immutable" import "package:meta/meta.dart" as meta))]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
pub struct UsbVersion(pub u8, pub u8, pub u8);

#[frb(dart_metadata=("freezed", "immutable" import "package:meta/meta.dart" as meta))]
pub struct UsbInfo {
    pub bus_number: u8,
    pub address: u8,
    pub vendor_id: u16,
    pub product_id: u16,
    pub num_configurations: u8,
    pub max_packet_size: u8,
    pub protocol_code: u8,
    pub sub_class_code: u8,
    pub class_code: u8,
    pub serial_number_string_index: Option<u8>,
    pub product_string_index: Option<u8>,
    pub manufacturer_string_index: Option<u8>,
    pub usb_version: UsbVersion,
    pub device_version: UsbVersion,
    pub descriptor_type: u8,
    pub length: u8,
    pub speed: UsbSpeed,
    device_origin: Device<GlobalContext>,
}

/// USB device speeds. Indicates the speed at which a device is operating.
/// - [libusb_supported_speed](http://libusb.sourceforge.net/api-1.0/group__libusb__dev.html#ga1454797ecc0de4d084c1619c420014f6)
/// - [USB release versions](https://en.wikipedia.org/wiki/USB#Release_versions)
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum UsbSpeed {
    /// The operating system doesn't know the device speed.
    Unknown,

    /// The device is operating at low speed (1.5 Mbps).
    Low,

    /// The device is operating at full speed (12 Mbps).
    Full,

    /// The device is operating at high speed (480 Mbps).
    High,

    /// The device is operating at super speed (5 Gbps).
    Super,

    /// The device is operating at super speed plus (10 Gbps).
    SuperPlus,
}

impl Into<UsbSpeed> for Speed {
    fn into(self) -> UsbSpeed {
        match self {
            Speed::Unknown => UsbSpeed::Unknown,
            Speed::Low => UsbSpeed::Low,
            Speed::Full => UsbSpeed::Full,
            Speed::High => UsbSpeed::High,
            Speed::Super => UsbSpeed::Super,
            Speed::SuperPlus => UsbSpeed::SuperPlus,
            _ => UsbSpeed::Unknown,
        }
    }
}

/// get all usb infos
#[frb(sync)]
pub fn get_usb_infos() -> Vec<UsbInfo> {
    rusb::devices().unwrap().iter().map(|i| i.into()).collect()
}

impl UsbInfo {
    //打开设备
    #[frb(sync)]
    pub fn open(&self) -> Result<UsbHandle, String> {
        let r = self.device_origin.open();
        match r {
            Ok(ok) => Ok(UsbHandle { handle: ok }),
            Err(e) => Err(e.to_string()),
        }
    }

    // 读取设备的名字
    #[frb(sync)]
    pub fn read_usb_name(&self) -> Result<UsbName, String> {
        match self.device_origin.open() {
            Ok(handle) => {
                let timeout = Duration::from_secs(60);
                if let Ok(languages) = handle.read_languages(timeout) {
                    if languages.len() > 0 {
                        let language = languages[0];
                        let device_desc = self.device_origin.device_descriptor().unwrap();
                        let manufacturer_name = handle
                            .read_manufacturer_string(language, &device_desc, timeout)
                            .ok();
                        let product_name = handle
                            .read_product_string(language, &device_desc, timeout)
                            .ok();
                        let serial_number = handle
                            .read_serial_number_string(language, &device_desc, timeout)
                            .ok();
                        Ok(UsbName {
                            manufacturer_name: manufacturer_name,
                            product_name: product_name,
                            serial_number: serial_number,
                        })
                    } else {
                        Err("Unable to obtain device name".to_string())
                    }
                } else {
                    Err("Unable to obtain device name".to_string())
                }
            }
            Err(e) => Err(e.to_string()),
        }
    }
}

#[frb(dart_metadata=("freezed", "immutable" import "package:meta/meta.dart" as meta))]
pub struct UsbName {
    pub manufacturer_name: Option<String>,
    pub product_name: Option<String>,
    pub serial_number: Option<String>,
}
pub struct UsbHandle {
    handle: DeviceHandle<GlobalContext>,
}

impl UsbHandle {
    ///读取数据
    #[frb(sync)]
    pub fn read_interrupt(self, endpoint: u8, timeout: u64, listen: StreamSink<Vec<u8>>) {
        let mut buffer = [0u8; 64];
        let handle = Arc::new(Mutex::new(self.handle));
        FLUTTER_RUST_BRIDGE_HANDLER
            .thread_pool()
            .0
            .execute(move || loop {
                let get_handle = handle.lock().unwrap();
                let size = get_handle.read_interrupt(
                    endpoint,
                    &mut buffer,
                    Duration::from_millis(timeout),
                );
                match size {
                    Ok(size_len) => {
                        let buf = &buffer[..size_len];
                        let _ = listen.add(buf.to_vec());
                        // let data = String::from_utf8_lossy(buf);
                        // let _ = listen.add(data.to_string());
                    }
                    Err(_) => todo!(),
                };
            });
    }
    ///写数据
    #[frb(sync)]
    pub fn write_data(&self, endpoint: u8, buf: &[u8], timeout: u64) -> Result<usize, String> {
        let r = self
            .handle
            .write_bulk(endpoint, buf, Duration::from_millis(timeout));
        match r {
            Ok(size) => Ok(size),
            Err(e) => Err(e.to_string()),
        }
    }

    ///设置设备配置(通常1)
    #[frb(sync)]
    pub fn set_active_configuration(&self, config: u8) {
        let _ = self.handle.set_active_configuration(config);
    }

    ///声明接口 (通常是0)
    #[frb(sync)]
    pub fn claim_interface(&self, iface: u8) {
        let _ = self.handle.claim_interface(iface);
    }

    ///释放接口
    #[frb(sync)]
    pub fn release_interface(&self, iface: u8) {
        let _ = self.handle.release_interface(iface);
    }
}

impl Into<UsbInfo> for Device<GlobalContext> {
    fn into(self) -> UsbInfo {
        let address = self.address();
        let desc = self.device_descriptor().unwrap();
        let speed = self.speed().into();
        return UsbInfo {
            speed,
            bus_number: self.bus_number(),
            address: address,
            vendor_id: desc.vendor_id(),
            product_id: desc.product_id(),
            num_configurations: desc.num_configurations(),
            max_packet_size: desc.max_packet_size(),
            protocol_code: desc.protocol_code(),
            sub_class_code: desc.sub_class_code(),
            class_code: desc.class_code(),
            serial_number_string_index: desc.serial_number_string_index(),
            product_string_index: desc.product_string_index(),
            manufacturer_string_index: desc.manufacturer_string_index(),
            usb_version: desc.usb_version().into(),
            device_version: desc.device_version().into(),
            descriptor_type: desc.descriptor_type(),
            length: desc.length(),
            device_origin: self,
        };
    }
}

impl Into<UsbVersion> for Version {
    fn into(self) -> UsbVersion {
        UsbVersion(self.0, self.1, self.2)
    }
}

///监听USB事件,它在线程池中执行
#[frb(sync)]
pub fn listen_usb_event_handle(listen: StreamSink<Vec<UsbInfo>>, sleep: Option<u64>) {
    FLUTTER_RUST_BRIDGE_HANDLER
        .thread_pool()
        .0
        .execute(move || loop {
            let infos = get_usb_infos();
            let _ = listen.add(infos);
            thread::sleep(Duration::from_millis(sleep.map_or(500, |v| v)))
        });
}
